package com.knife.oauth.filter;

import com.knife.oauth.constants.KnifeOauthConstant;
import com.knife.oauth.domain.entity.IamUser;
import com.knife.oauth.domain.service.AbstractKnifeUserDetailsBuilder;
import com.knife.oauth.util.ServerRequestUtils;
import com.knife.redis.KnifeRedisHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * jwt token过滤器
 * 1 获取token
 * 2 解析token中的用户信息
 * 3 从redis获取用户信息
 * 4 存入securityContextHolder
 *
 * @author： 76875
 * @date： 2022/4/14 星期四 14:24
 * @description：
 * @modifiedBy：
 * @version: 1.0
 */
@Slf4j
@Component
public class KnifeJwtAuthenticationTokenFilter extends OncePerRequestFilter implements KnifeOauthConstant {

    private final KnifeRedisHelper knifeRedisHelper;
    private final AbstractKnifeUserDetailsBuilder abstractKnifeUserDetailsBuilder;

    @Autowired
    public KnifeJwtAuthenticationTokenFilter(KnifeRedisHelper knifeRedisHelper,AbstractKnifeUserDetailsBuilder abstractKnifeUserDetailsBuilder) {
        this.knifeRedisHelper = knifeRedisHelper;
        this.abstractKnifeUserDetailsBuilder = abstractKnifeUserDetailsBuilder;
    }


    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        knifeRedisHelper.setCurrentDatabase(REDIS_DB);
        try {
            String token = ServerRequestUtils.parseToken(request);
            if (ObjectUtils.isEmpty(token)){
                filterChain.doFilter(request,response);
                // 其他过滤器调用完成后，返回到此处
                return;
            }
            // 该token记录不存在，则需要重新登录
            String userId = knifeRedisHelper.strGet(tokenKey(token));
            if (!ObjectUtils.isEmpty(userId)){
                // 将本 token 延期
                knifeRedisHelper.setExpire(tokenKey(token),480, TimeUnit.MINUTES);
                // 将用户信息存入securityContextHolder
                //SecurityContextImpl securityContext = new SecurityContextImpl(new JwtAuthenticationToken(jwtDecoder.decode(token)));
                //SecurityContextHolder.setContext(securityContext);
                // todo 补充权限信息到usernamePasswordAuthenticationToken
                IamUser iamUser = knifeRedisHelper.strGet(tokenUserKey(userId), IamUser.class);
                UserDetails userDetails = abstractKnifeUserDetailsBuilder.changeToUser(iamUser, iamUser.getIamMemberRoleList());
                UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(userDetails,null,userDetails.getAuthorities());
                SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
            }
            filterChain.doFilter(request,response);
        } finally {
            knifeRedisHelper.clearCurrentDatabase();
        }
    }
}
